#include "noeud.hpp"
#include "arc.hpp"
#include "element_generique.hpp"

#include <string>

void initNoeud(Noeud &n, const string & nom, bool verbose) {
    if (verbose)
        cout << "\tentrée dans initNoeud" << endl;


    if (verbose) {
        cout << " n :"<< &n << endl;
        cout << " n.nom : " << &(n.nom) << endl;
        cout << nom << endl;
    }

    n.nom = nom;


    if (verbose)
        cout << "\tnom ajouté" << endl;

    n.arc_inc_ext = NULL;
    n.nb_arc_ext = 0;
    n.capa_arc_ext = 1;
    n.arc_inc_ext = (Arc**) malloc(sizeof (Arc*) * n.capa_arc_ext);

    if (verbose)
        cout << "\ttableau d'arcs exterieurs initialisé" << endl;

    n.arc_inc_int = NULL;
    n.nb_arc_int = 0;
    n.capa_arc_int = 1;
    n.arc_inc_int = (Arc**) malloc(sizeof (Arc*) * n.capa_arc_int);

    if (verbose)
        cout << "\ttableau d'arcs interieurs initialisé" << endl << endl;
}

void initNoeud(Noeud &n, const Noeud &copie, bool verbose) {
    n.nom = copie.nom;

    if (verbose) {
        cout << "nom de n : " << n.nom << endl;
        cout << "nom de copie : " << copie.nom << endl;
    }

    n.capa_arc_ext = copie.capa_arc_ext;
    n.arc_inc_ext = (Arc**) malloc(sizeof (Arc*) * n.capa_arc_ext);
    n.nb_arc_ext = copie.nb_arc_ext;

    if (verbose) {
        cout << "nb_arc_ext de n : " << n.nb_arc_ext << endl;
        cout << "nb_arc_ext de copie : " << copie.nb_arc_ext << endl;

        cout << "capa_arc_ext de n : " << n.capa_arc_ext << endl;
        cout << "capa_arc_ext de copie : " << copie.capa_arc_ext << endl;

    }


    for (int i = 0; i < n.nb_arc_ext; i++) {
        n.arc_inc_ext[i] = copie.arc_inc_ext[i];

        if (verbose) {
            cout << "arc de n" << endl;
            afficheArc(n.arc_inc_ext[i]);
            cout << "arc de copie" << endl;
            afficheArc(copie.arc_inc_ext[i]);
        }

    }

    n.capa_arc_int = copie.capa_arc_int;
    n.arc_inc_int = (Arc**) malloc(sizeof (Arc*) * n.capa_arc_int);
    n.nb_arc_int = copie.nb_arc_int;

    if (verbose) {
        cout << "nb_arc_int de n : " << n.nb_arc_int << endl;
        cout << "nb_arc_int de copie : " << copie.nb_arc_int << endl;

        cout << "capa_arc_int de n : " << n.capa_arc_int << endl;
        cout << "capa_arc_int de copie : " << copie.capa_arc_ext << endl;

    }

    for (int i = 0; i < n.nb_arc_int; i++) {
        n.arc_inc_int[i] = copie.arc_inc_int[i];

        if (verbose) {
            cout << "arc de n" << endl;
            afficherArc(*(n.arc_inc_int[i]));
            cout << "arc de copie" << endl;
            afficherArc(*(copie.arc_inc_int[i]));
        }
    }

    if (verbose)
        cout << endl;
}

void ajoutArcExt(Noeud &n, Arc * arc_ext, bool verbose) {
    if (n.nb_arc_ext == n.capa_arc_ext - 1) {
        n.capa_arc_ext *= 2;
        n.arc_inc_ext = (Arc **) realloc(n.arc_inc_ext, sizeof(Arc*) * n.capa_arc_ext);
    }

    n.arc_inc_ext[n.nb_arc_ext] = arc_ext;

    if (verbose) {
        cout << "dans " << n.nom << endl;
        cout << "arc à ajouter dans arc_ext" << endl;
        afficherArc(*arc_ext);

        cout << "arc_ext ajouté à l'indice " << n.nb_arc_ext << endl;
        afficherArc(*(n.arc_inc_ext[n.nb_arc_ext]));

    }

    n.nb_arc_ext++;

    if (verbose)
        cout << endl;
}

void ajoutArcInt(Noeud &n, Arc * arc_int, bool verbose) {
    if (n.nb_arc_int == n.capa_arc_int - 1) {
        n.capa_arc_int *= 2;
        n.arc_inc_int = (Arc **) realloc(n.arc_inc_int, sizeof(Arc*) * n.capa_arc_int);
    }

    n.arc_inc_int[n.nb_arc_int] = arc_int;

    if (verbose) {
        cout << "dans " << n.nom << endl;
        cout << "arc à ajouter dans arc_int" << endl;
        afficherArc(*arc_int);

        cout << "arc_int ajouté à l'indice " << n.nb_arc_int << endl;
        afficherArc(*(n.arc_inc_int[n.nb_arc_int]));

        cout << endl;
    }

    n.nb_arc_int++;
}

void copieNoeud(Noeud &n, const Noeud &copie, bool verbose) {
    testamentNoeud(n, verbose);
    initNoeud(n, copie, verbose);
}

int compNoeud(const Noeud &n1, const Noeud &n2, bool verbose) {
    return n1.nom.compare(n2.nom);
}

string valeurNoeud(const Noeud &n, bool verbose) {
    return n.nom;
}

void afficherNoeud(const Noeud &n, bool verbose) {
    cout << valeurNoeud(n) << endl;
    cout << "\tArcs incidents extérieurs : " << endl;
    for (int i = 0; i < n.nb_arc_ext; i++) {
        afficherArc(*(n.arc_inc_ext[i]));
    }

    cout << "\tArcs incidents intérieurs : " << endl;
    for (int i = 0; i < n.nb_arc_int; i++) {

        afficherArc(*(n.arc_inc_int[i]));
    }
}

void testamentNoeud(Noeud &n, bool verbose) {

    for (int i = 0; i < n.nb_arc_ext; i++) {
        testamentArc(*(n.arc_inc_ext[i]));
        free(n.arc_inc_ext[i]);
    }

    free(n.arc_inc_ext);

    for (int i = 0; i < n.nb_arc_int; i++) {
        testamentArc(*(n.arc_inc_int[i]));
        free(n.arc_inc_int[i]);
    }

    free(n.arc_inc_int);
}
